﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using PPT = Microsoft.Office.Interop.PowerPoint;

namespace An_Im.Tool
{
    /// <summary>
    /// 动画录制模块。
    /// </summary>
    public static class AnimationRecorder
    {
        static Dictionary<PPT.MsoAnimType, string> typedic1;
        static Dictionary<string, PPT.MsoAnimType> typedic2;
        static Dictionary<PPT.MsoAnimProperty, string> propdic1;
        static Dictionary<string, PPT.MsoAnimProperty> propdic2;

        static AnimationRecorder()
        {
            typedic1 = new Dictionary<PPT.MsoAnimType, string>();
            typedic2 = new Dictionary<string, PPT.MsoAnimType>();
            propdic1 = new Dictionary<PPT.MsoAnimProperty, string>();
            propdic2 = new Dictionary<string, PPT.MsoAnimProperty>();

            AddTypeDicRecord(PPT.MsoAnimType.msoAnimTypeSet, "设置");
            AddTypeDicRecord(PPT.MsoAnimType.msoAnimTypeProperty, "属性");
            AddTypeDicRecord(PPT.MsoAnimType.msoAnimTypeColor, "颜色");
            AddTypeDicRecord(PPT.MsoAnimType.msoAnimTypeScale, "比例");
            AddTypeDicRecord(PPT.MsoAnimType.msoAnimTypeRotation, "旋转");
            AddTypeDicRecord(PPT.MsoAnimType.msoAnimTypeFilter, "滤镜");
            AddTypeDicRecord(PPT.MsoAnimType.msoAnimTypeMotion, "移动");

            AddPropDicRecord(PPT.MsoAnimProperty.msoAnimX, "X");
            AddPropDicRecord(PPT.MsoAnimProperty.msoAnimY, "Y");
            AddPropDicRecord(PPT.MsoAnimProperty.msoAnimVisibility, "可见性");
            AddPropDicRecord(PPT.MsoAnimProperty.msoAnimWidth, "宽度");
            AddPropDicRecord(PPT.MsoAnimProperty.msoAnimHeight, "高度");
            AddPropDicRecord(PPT.MsoAnimProperty.msoAnimColor, "颜色");
            AddPropDicRecord(PPT.MsoAnimProperty.msoAnimOpacity, "透明度");
            AddPropDicRecord(PPT.MsoAnimProperty.msoAnimRotation, "角度");

            // var app = Marshal.GetActiveObject("PowerPoint.Application") as PPT.Application;
            // app.WindowSelectionChange += App_WindowSelectionChange;


        }

        static void AddTypeDicRecord(PPT.MsoAnimType animType, string name)
        {
            typedic1.Add(animType, name);
            typedic2.Add(name, animType);
        }
        static void AddPropDicRecord(PPT.MsoAnimProperty animType, string name)
        {
            propdic1.Add(animType, name);
            propdic2.Add(name, animType);
        }

        private static void App_WindowSelectionChange(PPT.Selection Sel)
        {
            if (Sel.Type == PPT.PpSelectionType.ppSelectionShapes)
            {
                var shape = Sel.ShapeRange[1];
                var slide = shape.Parent as PPT.Slide;
                foreach (PPT.Effect eff in slide.TimeLine.MainSequence)
                {
                    if (eff.Shape == shape)
                    {
                        RecordArtificialEffect(eff, "默认");
                    }
                }

            }
        }

        private static string GetTimeDetail(PPT.Timing tim)
        {
            return string.Format(Properties.Resources.TimeDetail,
               tim.Duration,
               tim.TriggerDelayTime,
               tim.RepeatCount == int.MinValue ? "forever" : tim.RepeatCount.ToString(),
               tim.SmoothStart,
               tim.SmoothEnd,
               tim.BounceEnd,
               tim.Accelerate,
               tim.Decelerate,
               tim.BounceEndIntensity,
               tim.AutoReverse);

        }



        /// <summary>
        /// 录制原生效果。
        /// </summary>
        /// <param name="eff"></param>
        /// <param name="tags"></param>
        /// <returns></returns>
        public static string RecordNativeEffect(PPT.Effect eff, string tags)
        {
            var sb = new StringBuilder();

            var shp = eff.Shape;
            var tim = eff.Timing;
            var sb2 = new StringBuilder();

            var btiming = GetTimeDetail(tim);

            if (eff.EffectType == PPT.MsoAnimEffect.msoAnimEffectSpin)
            {
                sb2.Append(eff.Behaviors[1].RotationEffect.By);
            }
            else if (eff.EffectType == PPT.MsoAnimEffect.msoAnimEffectGrowShrink)
            {
                sb2.Append(eff.Behaviors[1].ScaleEffect.ByX); sb2.Append(",");
                sb2.Append(eff.Behaviors[1].ScaleEffect.ByY);
            }
            else if ((int)eff.EffectType >= (int)PPT.MsoAnimEffect.msoAnimEffectPathCircle)
            {
                sb2.Append(eff.Behaviors[1].MotionEffect.Path);
            }

            sb.AppendFormat(Properties.Resources.NativeEffectNode1,
                shp.Name.Trim().Replace(' ', '_'),
                tags,
                shp.TextEffect.Text,
               btiming,
                eff.EffectType,
                eff.Exit, sb2,
                shp.AnimationSettings.TextUnitEffect);

            sb.AppendLine();
            sb.AppendFormat(Properties.Resources.NativeEffectNode2);
            sb.AppendLine();
            sb.AppendLine();
            return sb.ToString();
        }

        /// <summary>
        /// 录制人工效果。
        /// </summary>
        /// <param name="eff"></param>
        /// <param name="tags"></param>
        /// <returns></returns>
        public static string RecordArtificialEffect(PPT.Effect eff, string tags)
        {
            var sb = new StringBuilder();

            var shp = eff.Shape;
            var tim = eff.Timing;

            var timing = GetTimeDetail(tim);

            sb.AppendFormat(Properties.Resources.EffectNode1,
                shp.Name.Trim().Replace(' ', '_'),
                tags,
                shp.TextEffect.Text,
                timing,
                shp.AnimationSettings.TextUnitEffect);
            sb.AppendLine();

            foreach (PPT.AnimationBehavior behavior in eff.Behaviors)
            {
                var btim = behavior.Timing;
                var btiming = GetTimeDetail(btim);

                switch (behavior.Type)
                {
                    case PPT.MsoAnimType.msoAnimTypeMotion:
                        sb.AppendFormat(Properties.Resources.MotionNode,
                            typedic1[behavior.Type],
                           btiming,
                            behavior.MotionEffect.FromX,
                            behavior.MotionEffect.FromY,
                            behavior.MotionEffect.ToX,
                            behavior.MotionEffect.ToY,
                            behavior.MotionEffect.ByX,
                            behavior.MotionEffect.ByY,
                            behavior.MotionEffect.Path);
                        sb.AppendLine();
                        break;
                    case PPT.MsoAnimType.msoAnimTypeColor:
                        sb.AppendFormat(Properties.Resources.ColorNode,
                            typedic1[behavior.Type],
                             btiming,
                            behavior.ColorEffect.From.RGB,
                            behavior.ColorEffect.To.RGB,
                            behavior.ColorEffect.By.RGB);
                        sb.AppendLine();
                        break;
                    case PPT.MsoAnimType.msoAnimTypeScale:
                        sb.AppendFormat(Properties.Resources.ScaleNode,
                            typedic1[behavior.Type],
                            btiming,
                            behavior.ScaleEffect.FromX,
                            behavior.ScaleEffect.FromY,
                            behavior.ScaleEffect.ToX,
                            behavior.ScaleEffect.ToY,
                            behavior.ScaleEffect.ByX,
                            behavior.ScaleEffect.ByY);
                        sb.AppendLine();
                        break;
                    case PPT.MsoAnimType.msoAnimTypeRotation:
                        sb.AppendFormat(Properties.Resources.RotationNode,
                            typedic1[behavior.Type],
                           btiming,
                            behavior.RotationEffect.From,
                            behavior.RotationEffect.To,
                            behavior.RotationEffect.By);
                        sb.AppendLine();
                        break;
                    case PPT.MsoAnimType.msoAnimTypeProperty:
                        sb.AppendFormat(Properties.Resources.PropNode1,
                           typedic1[behavior.Type],
                           btiming,
                           propdic1[behavior.PropertyEffect.Property],
                           behavior.PropertyEffect.From,
                           behavior.PropertyEffect.To);
                        foreach (PPT.AnimationPoint point in behavior.PropertyEffect.Points)
                        {
                            sb.AppendFormat(Properties.Resources.PointNode,
                                point.Time,
                                point.Value,
                                point.Formula);

                            sb.AppendLine();
                        }
                        sb.AppendFormat(Properties.Resources.PropNode2);
                        sb.AppendLine();
                        break;
                    case PPT.MsoAnimType.msoAnimTypeFilter:
                        string subtype = "none";
                        try
                        {
                            subtype = ((int)behavior.FilterEffect.Subtype).ToString();
                        }
                        catch { }
                        sb.AppendFormat(Properties.Resources.FilterNode,
                            typedic1[behavior.Type],
                            btiming,
                            behavior.FilterEffect.Reveal,
                            behavior.FilterEffect.Type,
                            subtype);
                        sb.AppendLine();

                        break;
                    case PPT.MsoAnimType.msoAnimTypeSet:
                        sb.AppendFormat(Properties.Resources.SetNode,
                            typedic1[behavior.Type],
                            btiming,
                            propdic1[behavior.SetEffect.Property],
                            behavior.SetEffect.To);
                        sb.AppendLine();

                        break;
                    default:
                        break;
                }
            }
            sb.AppendFormat(Properties.Resources.EffectNode2);
            sb.AppendLine();
            sb.AppendLine();
            return sb.ToString();
        }


    }


}
